package src; 
import java.awt.*;
import java.util.*;

import javax.swing.JOptionPane;

/**
 * All the logic of SuperTicTacToe (rules, players, turns) is all housed in Game. Game communicates with the GUI via the Controller
 * and interprets all moves made by Players (including if they are valid). Delegates tasks to Board, such as keeping track of which spots
 * are occupied on the grid, or whether or not the grid has been won, etc. 
 * @author Akshat
 *
 */
public class SuperTicTacToeGame 
{
	protected SuperTicTacToeController controller; 
	
	protected Player[] players; 
	protected int currPlayerIndex; 

	protected Board board;
	protected SubGrid currSubGrid; 
	
	private boolean won;
	
	public SuperTicTacToeGame(SuperTicTacToeController c)
	{
		controller = c; 
		won = false; 
		
		board = new Board();
		currSubGrid = board.get(1,1); //start game in center of board. 
		
		players = new Player[2]; 		
		currPlayerIndex = 0; 
	}
	
	/**
	 * Takes an array of two players (from GUI_Login) and sets them as the players
	 * for this game. Then, tells players that this is the game they are playing. 
	 * @param p players for the game
	 */
	public void setPlayers(Player[] p)
	{
		players = p; 
		
		for( Player player: players)
		{
			player.setGame(this);
		}
		
		System.out.println("working 3");
	}
	
	/**
	 * Sets the players to a set of default HumanPlayers. Used mostly for testing purposes. 
	 */
	public void setPlayers()
	{
		players[0] = new HumanPlayer("Akshat", Color.BLUE);
		players[1] = new HumanPlayer("Arjun", Color.RED);
		
		for( Player player: players)
		{
			player.setGame(this);
		}
		
		System.out.println("working 3");
	}
	
	/**
	 * Turn-based logic of the game. Player.play() calls getPlay() which waits for setPlay() to be called. Thus, game will not advance
	 * until setPlay() called (if Human Player). This can be achieved by clicking a valid location on the grid. 
	 */
	public void playGame()
	{
		System.out.println(getCurrentPlayer() +"'s turn"); 
		
		while( !won && board.canPlay() )
		{
			getCurrentPlayer().play(); 
			
			controller.repaintGUI();
			
			won = board.checkForWinner(); 			

			if( !won && board.canPlay() )
			{
				currPlayerIndex += 1; 
				currPlayerIndex %= 2;
		
				System.out.println(getCurrentPlayer() +"'s turn"); 
			}
		}
		
	}
	
	/**
	 * Resets game variables in order to play another game. Resets "won", makes new Board, 
	 * resets current sub grid and current player. 
	 */
	public void reset()
	{
		won = false; 
		board = new Board(); 
		currSubGrid = board.get(1,1); //start game in center of board. 
		currPlayerIndex = 0; 
	}
	
	/**
	 * Getter method for private won variable
	 * @return has game been won? 
	 */
	public boolean getWon()
	{
		return won; 
	}
	
	
	/**
	 * Some of the main logic of the game. Checks if move is valid, specifically if it is in the correct subGrid.
	 * If all tests are passed, the current player's location is set, allowing player.getPlay() to run, which allows player.play() to run
	 * which allows the game to progress.
	 * 
	 * @param loc Location on board which was clicked. 
	 */
	public void moveMade(GridLocation loc)
	{
		if( currSubGrid != null && !currSubGrid.canPlay())
		{
			currSubGrid = null; 
		}	
		
		if(players[currPlayerIndex] instanceof HumanPlayer)
		{
			if(currSubGrid == null || (loc.getMainRow() == currSubGrid.getMainRow() && loc.getMainCol() == currSubGrid.getMainCol()))
			{
				if( currSubGrid != null && currSubGrid.getOpenLocations().contains(loc) )
				{
					players[currPlayerIndex].setPlay(loc);
					currSubGrid = board.get(loc.getSubRow(), loc.getSubCol());
				}
				else if( currSubGrid == null && board.get(loc.getMainRow(), loc.getMainCol()).getOpenLocations().contains(loc))
				{
					players[currPlayerIndex].setPlay(loc);
					currSubGrid = board.get(loc.getSubRow(), loc.getSubCol());
				}
				else
				{
					System.out.println("Invalid spot!"); 
					return;
				}
			}
			else
			{
				System.out.println("Incorrect Grid!"); 
				return; 
			}
		}
		else
		{
		    currSubGrid = board.get(loc.getSubRow(), loc.getSubCol());
		}
		
		if( currSubGrid != null && !currSubGrid.canPlay())
		{
			currSubGrid = null; 
		}
		
	}
	
	/**
	 * @return reference to game board
	 */
	public Board getBoard()
	{
		return board; 
	}
	
	/**
	 * @return reference to current sub grid
	 */
	public SubGrid getCurrentSubGrid()
	{
		return currSubGrid;
	}
	
	/**
	 * @return reference to current player
	 */
	public Player getCurrentPlayer()
	{
		return players[currPlayerIndex];
	}

}

